#include <cserver/restapi.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
#include <pqxx/transaction.hxx>

#include <sstream>

namespace csrv{ namespace webcmd{
	static const char* K_this_command= "api/v1/common/adduser";

	void add_user(Request& req, pqxx::connection& dbconn, SessionContext& sctx, const std::string& /*cmd*/ ){
		auto query = parseQuery(req.getParam("QUERY_STRING"));
		auto& callback = query["callback"];
		auto sessionid = req.getCookie("sessionid");

		StreamGroup sg(req, 4096);
		boost::property_tree::ptree ptree;
		read_json(sg.fin, ptree);
		auto account = ptree.get<std::string>("account", "");
		auto password = ptree.get<std::string>("password", "");
		auto name = ptree.get<std::string>("name", "");
		auto role = ptree.get<std::string>("role", "");

		UserInfo uinfo;
		std::string current_account;
		bool account_exist = false;
		bool is_admin = false;
		bool role_exist = false;
		{
			std::lock_guard<std::mutex> guard(sctx.mutex);
			auto pos = sctx.activeSessions.find(sessionid);
			// assert( pos != master.sessions.activeSessions.end());
			is_admin = sctx.user_info.find(pos->second)->second.role == "admin";

			account_exist = sctx.user_info.count(account) != 0;
			role_exist = sctx.role_permission.count(role) != 0;
		}

		if (!is_admin){
			response_error(sg.fout, 403, "ErrPermission", "PermissionDenied", req);
			return;
		}
		if (account_exist ){
			response_error(sg.fout, 400, "ErrParameter", "AccountExist", req);
			return;
		}
		if (account.empty() || !role_exist || name.empty()){
			response_error(sg.fout, 400, "ErrParameter", "BadParameter", req);
			return;

		}

		password = hash_password(account, password);
		pqxx::work w(dbconn);
		w.prepared("adduser")(account)(name)(password)(role).exec();
		auto result = w.prepared("get_userid")(account).exec();
		std::string userid = result.begin()->begin()->c_str();
		w.commit();

		{
			std::lock_guard<std::mutex> guard(sctx.mutex);
			auto& uinfo = sctx.user_info[account];
			uinfo.displayName = name;
			uinfo.password = password;
			uinfo.role = role;
			uinfo.userid = userid;
		}

		response_header(sg.fout, 200);
		if (!callback.empty()) sg.fout << callback << "(";

		sg.fout << boost::format(R"({
"func":"moduser",
"args":{"account":%1%},
"ret":{"success":true, "message":"", "userid":%2%}
})") 
			% escape_string(account) % escape_string(userid);

		if (!callback.empty()) sg.fout << ")";
	}

}
static CommandAddHelper k_registerHandler("PUT", webcmd::K_this_command, &webcmd::add_user, {"admin"});
}



